/**
 * 
 */
package simulation;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;

/**
 * @author aclayton
 *
 */
public class Configuration implements Serializable{
	private HashMap<Robot, Circle> positions;
	private Rect boundingBox;
	
	public Configuration(HashMap<Robot, Circle> config){
		this.positions = config;
		this.boundingBox = null;
	}
	
	public Configuration(HashMap<Robot, Circle> config, Rect boundingBox){
		this.positions = config;
		this.boundingBox = boundingBox;
	}
	
	
	public ArrayList<Robot> getRobots(){
		return new ArrayList<Robot>(positions.keySet());
	}
	
	public boolean inFreeSpace(Map map){
		
		Collection<Circle> co = positions.values();
		
		
		
		
		for(Circle c : co){
			if(!map.getBoundingBox().pointInBox(c.getCenter()))
				return false;
			
			for(Obstacle ob : map.getObstacles()){
				if(ob.intersectsCircle(c))
					return false;
			}
		}
		
		for(Circle c : co){
			for(Circle c2 : positions.values()){
				if(c != c2 && c.intersectsCircle(c2)){
					c.intersectsCircle(c2);
					return false;
					
				}
			}
		}
		
		return true;
	}
	
	
	public Circle getRobotPosition(Robot r){
		return positions.get(r);
	}
	
	
	public ArrayList<Circle> getPositions(){
		return new ArrayList<Circle>(positions.values());
	}
	
	public Point getConfigCenter(){
		double x = 0,y = 0;
		
		for(Circle c : positions.values()){
			x += c.getCenter().getX();
			y += c.getCenter().getY();
		}
		
		return new Point(x/positions.size(), y/positions.size());
	}
	
	public double getDistanceFromConfig(Configuration c){
		return getConfigCenter().getDistance(c.getConfigCenter());
	}
	
	public String toString(){
		String str = "Configuration_Start";
		
		for(Robot r : getRobots())
			str = str + "\nRobotPositon(" + r.getRobotNumber() + "," + positions.get(r).getCenter().getX() + "," + positions.get(r).getCenter().getY()+")";
		
		return str + "\n" + "Configuration_End";
			
	}
	
	public void calculateBoundingBox(){
		boundingBox = null;
		for(Circle c : positions.values()){
			if(boundingBox == null)
				boundingBox = c.getBoundingBox();
			else
				boundingBox = boundingBox.union(c.getBoundingBox());
		}
	}
	
	public Rect getBoundingBox(){
		return boundingBox;
	}
	
	public static Configuration CreateFromString(Simulation sim, String s){
		int tempBegin = s.indexOf("RobotPositon(");
		String temp = s.substring(tempBegin);
		tempBegin = temp.indexOf("\nConfiguration_End");
		temp = temp.substring(0,tempBegin);
		
		HashMap<Robot, Circle> map = new HashMap<Robot, Circle>();
		
		String str[] = temp.split("\\)");
		System.out.println(str.length);
		for(String tempstr : str){
			System.out.println(tempstr);
			int a = tempstr.indexOf("R");
			
			String tempstr2 = tempstr.substring(a);
			tempstr2 = tempstr2.substring(13);
			
			String nums[] = tempstr2.split(",");
			int robotnum = Integer.parseInt(nums[0]);
			double x = Double.parseDouble(nums[1]);
			double y = Double.parseDouble(nums[2]);
			
			Robot r = sim.getRobotNum(robotnum);
			Circle c = new Circle(new Point(x,y), r.getRadius());
			
			map.put(r, c);
			//Robot(robotnum, x, y);
		}
		
		
		return new Configuration(map);
	}
	
	public static Configuration CreateRandomConfig(Simulation sim, Rect boundingBox){
		HashMap<Robot, Circle> mapping = new HashMap<Robot, Circle>();
		HashSet<Robot> robs = sim.getRobot();
		
		Map m = sim.getMap();
		
		for(Robot r : robs){
			Point pt = Point.getRandomPointInBox(boundingBox);
			Circle c = new Circle(pt, r.getRadius());
			mapping.put(r, c);
		}
		
		return new Configuration(mapping);
	}
	
	public static Configuration CreateRandomFreeConfig(Simulation sim, Rect boundingBox){
		Configuration con = CreateRandomConfig(sim, boundingBox);
		while(!con.inFreeSpace(sim.getMap()))
			con = CreateRandomConfig(sim, boundingBox);
		return con;
	}
	
	public static Configuration CreateRandomConfigInCircle(Simulation sim, Rect boundingBox, double radius){
		Point p = Point.getRandomPointInBox(boundingBox), pt;
		Circle c = new Circle(p, radius);
		Rect box = null;
		
		HashSet<Robot> robs = sim.getRobot();
		Map m = sim.getMap();
		
		HashMap<Robot, Circle> hashmap = new HashMap<Robot, Circle>();
		boolean firstset = true;
		
		Circle c2;
		Robot r2;
		for(Robot r : robs){
			if(firstset){
				c2 = new Circle(p, r.getRadius());
				box = c2.getBoundingBox();
				firstset = false;
			} else {
				pt = Point.getRandomPointInCircle(c);
				c2 = new Circle(pt, r.getRadius());
				box = box.union(c2.getBoundingBox());
			}
			
			hashmap.put(r, c2);
		}
		
		return new Configuration(hashmap, box);
	}
	
	public static Configuration CreateRandomFreeConfigInCircle(Simulation sim, Rect boundingBox, double radius){
		Configuration con = CreateRandomConfigInCircle(sim, boundingBox, radius);
		while(!con.inFreeSpace(sim.getMap()))
			con = CreateRandomConfigInCircle(sim, boundingBox, radius);
		return con;
	}
	
	
	public static void main(String[] args) {
		Map m = new Map(10,10);
		Robot r = new Robot(5,1);
		Robot r2 = new Robot(6,1);
		Circle c = new Circle(new Point(1,1), 1);
		Circle c2 = new Circle(new Point(3,1), 1);
		HashMap<Robot, Circle> h = new HashMap<Robot, Circle>();
		h.put(r, c);
		h.put(r2, c2);
		
		//Configuration con = new Configuration(m, h);
		//String s = con.toString();
		//System.out.println(s);
		
		//Configuration con2 = Configuration.CreateFromString(s);
	}
}
